package com.csw.android.ffmpegtest.media.play

import android.content.Context
import android.media.AudioAttributes
import android.media.AudioFormat
import android.media.AudioManager
import android.media.AudioTrack
import androidx.lifecycle.LifecycleOwner
import com.csw.android.dev_utils.ex.CloseableEx.closeIgnoreException
import com.csw.android.ffmpegtest.app.MyApplication
import com.csw.android.ffmpegtest.media.base.WAVHelper
import com.csw.android.ffmpegtest.media.play.base.BasePlayer
import com.csw.android.ffmpegtest.media.play.base.IPlayerListener
import java.io.FileInputStream

class WAVPlayer(fp: String, lifecycleOwner: LifecycleOwner, listener: IPlayerListener) :
    BasePlayer(fp, lifecycleOwner, listener) {

    private var startTime: Long = 0
    private var duration: Long = 0
    private val playThread = PlayThread()
    private val runningPost = object : Runnable {
        override fun run() {
            onRunning(duration, System.currentTimeMillis() - startTime)
            if (working) {
                mainHandler.postDelayed(this, 1000 / 60)
            }
        }
    }

    override fun start(): Boolean {
        if (super.start()) {
            working = true
            playThread.start()
            onStart()

            return true
        }
        return false
    }

    override fun stop(): Boolean {
        if (super.stop()) {
            working = false
            return true
        }
        return false
    }

    override fun release() {
        super.release()
        working = false
        mainHandler.removeCallbacks(runningPost)
    }

    private inner class PlayThread : Thread() {

        override fun run() {
            super.run()
            var fis: FileInputStream? = null
            var audioTrack: AudioTrack? = null
            try {
                val wavInfo =
                    WAVHelper.getWAVInfo(getFilePath()) ?: throw RuntimeException("未能读取wav文件信息")
                duration = WAVHelper.getAudioDuration(wavInfo)
                startTime = System.currentTimeMillis()
                mainHandler.post(runningPost)
                val audioManager =
                    MyApplication.instance.getSystemService(Context.AUDIO_SERVICE) as AudioManager
                val sessionId = audioManager.generateAudioSessionId()
                val channelConfig =
                    if (wavInfo.channels == 2) AudioFormat.CHANNEL_OUT_STEREO else AudioFormat.CHANNEL_OUT_MONO
                val bufferSize = AudioTrack.getMinBufferSize(
                    wavInfo.sampleRateInHz,
                    channelConfig,
                    wavInfo.encoding
                )
                audioTrack = AudioTrack(
                    AudioAttributes.Builder()
                        .setLegacyStreamType(AudioManager.STREAM_MUSIC)
                        .build(),
                    AudioFormat.Builder()
                        .setChannelMask(channelConfig)
                        .setEncoding(wavInfo.encoding)
                        .setSampleRate(wavInfo.sampleRateInHz)
                        .build(),
                    bufferSize,
                    AudioTrack.MODE_STREAM,
                    sessionId
                ).apply {
                    play()
                }
                fis = FileInputStream(getFilePath()).apply {
                    val buff = ByteArray(bufferSize)
                    var len: Int
                    var currTime: Long
                    while (read(buff).also { len = it } > 0) {
                        if (!working) {
                            break
                        }
                        audioTrack.write(buff, 0, len)
                    }
                }
                onComplete()
            } catch (e: Exception) {
                onError(e)
            } finally {
                fis.closeIgnoreException()
                audioTrack?.release()
            }
        }
    }
}